Skip to content

Add launch metadata for runs#343

Open
mezz wants to merge 1 commit into
neoforged:mainfrom
mezz:pr/launch-metadata
Open

Add launch metadata for runs#343
mezz wants to merge 1 commit into
neoforged:mainfrom
mezz:pr/launch-metadata

Conversation

@mezz

@mezz mezz commented Jul 8, 2026

Copy link
Copy Markdown

Context

JEI needs client tests that can start external dedicated servers.

Today, doing that from another project means reading MDG generated classpath, VM args, and program args files directly. That works, but it depends on internal build/moddev file names and requires downstream code to know how MDG assembles a launch command.

Changes

This change adds a public CreateLaunchMetadata task for each configured run.

For a run named server, MDG registers:

createServerLaunchMetadata

The task writes:

build/moddev/serverLaunchMetadata.properties

The properties file contains:

  • workingDirectory
  • javaExecutable
  • classpathArgsFile
  • vmArgsFile
  • programArgsFile
  • mainClass
  • modFolders
  • environment.<name> entries for run environment variables

There is also a createLaunchMetadata aggregate task.

The metadata writer uses the JDK Properties format so consumers can load it with standard properties readers, while MDG keeps the output sorted and comment-free for stable task output.

Launchers should treat workingDirectory as part of the metadata contract. If they need disposable or test-specific state, they should configure the run gameDirectory instead of replacing the metadata working directory at launch time.

This also adds Gradle daemon JVM criteria for Java 17 so local wrapper invocations use a supported JVM by default.

Why

This gives consumers like JEI a typed Gradle task output to depend on:

tasks.named("createServerLaunchMetadata", CreateLaunchMetadata).flatMap {
    it.metadataFile
}

Downstream builds can use the metadata without reconstructing MDG launch details from internal file naming conventions.

Validation

  • ./gradlew test --tests net.neoforged.moddevgradle.tasks.CreateLaunchMetadataTest
  • ./gradlew test --tests net.neoforged.moddevgradle.functional.LaunchMetadataFunctionalTest
  • ./gradlew javaImmaculateCheck

I validated this branch locally using JEI with --include-build ../ModDevGradle. After simplifying some code there, I was able to successfully run my tests:

  • :NeoForge:runClientRecipeSyncTest
  • NeoForge external server with JEI passed
  • NeoForge external server without JEI passed
  • vanilla external server without JEI passed

JEI configures each external server run with a JEI-owned build directory as gameDirectory, consumes CreateLaunchMetadata, and launches using the metadata workingDirectory unchanged.

Coverage includes:

  • per-run metadata
  • the createLaunchMetadata aggregate task
  • generated arg-file paths
  • properties escaping and ordering

## Context

JEI needs client tests that can start external dedicated servers.

Today, doing that from another project means reading MDG generated classpath, VM args, and program args files directly. That works, but it depends on internal `build/moddev` file names and requires downstream code to know how MDG assembles a launch command.

## Changes

This change adds a public `CreateLaunchMetadata` task for each configured run.

For a run named `server`, MDG registers:

```groovy
createServerLaunchMetadata
```

The task writes:

```text
build/moddev/serverLaunchMetadata.properties
```

The properties file contains:

- `workingDirectory`
- `javaExecutable`
- `classpathArgsFile`
- `vmArgsFile`
- `programArgsFile`
- `mainClass`
- `modFolders`
- `environment.<name>` entries for run environment variables

There is also a `createLaunchMetadata` aggregate task.

The metadata writer uses the JDK Properties format so consumers can load it with standard properties readers, while MDG keeps the output sorted and comment-free for stable task output.

Launchers should treat `workingDirectory` as part of the metadata contract. If they need disposable or test-specific state, they should configure the run `gameDirectory` instead of replacing the metadata working directory at launch time.

This also adds Gradle daemon JVM criteria for Java 17 so local wrapper invocations use a supported JVM by default.

## Why

This gives consumers like JEI a typed Gradle task output to depend on:

```groovy
tasks.named("createServerLaunchMetadata", CreateLaunchMetadata).flatMap {
    it.metadataFile
}
```

Downstream builds can use the metadata without reconstructing MDG launch details from internal file naming conventions.

## Validation

- `./gradlew test --tests net.neoforged.moddevgradle.tasks.CreateLaunchMetadataTest`
- `./gradlew test --tests net.neoforged.moddevgradle.functional.LaunchMetadataFunctionalTest`
- `./gradlew javaImmaculateCheck`

JEI validated this branch with `--include-build ../ModDevGradle`:

- `:NeoForge:runClientRecipeSyncTest`
- NeoForge external server with JEI passed
- NeoForge external server without JEI passed
- vanilla external server without JEI passed

JEI configures each external server run with a JEI-owned build directory as `gameDirectory`, consumes `CreateLaunchMetadata`, and launches using the metadata `workingDirectory` unchanged.

Coverage includes:

- per-run metadata
- the `createLaunchMetadata` aggregate task
- generated arg-file paths
- properties escaping and ordering
@neoforged-pr-publishing

Copy link
Copy Markdown
  • Publish PR to GitHub Packages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant